from __future__ import with_statement
from math import sqrt
from threading import Thread
from threading import Lock
from time import time
from time import sleep
from PyQt4 import QtGui
from PyQt4 import QtCore
import sys

__author__="Pablo Rojas Valdes"
__date__ ="$Jul 18, 2011$"

class Element:
    def __init__(self, tag=None):
        self.__id = 0
        self.__tag = tag
    
    def setId(self, id):
        self.__id = id
        
    def setTag(self, tag):
        self.__tag = tag
        
    def getId(self):
        return self.__id
    
    def getTag(self):
        return self.__tag
   
    @staticmethod
    def convertCoordinates(size, viewport, location):
        width, height = size
        xLow, yLow, xUp, yUp = viewport
        x, y = location
        
        lx = ((x*width)/xUp)-xLow
        ly = height - (((y*height)/yUp) - yLow)
        return (lx, ly)
        
    @staticmethod
    def convertDimension(size, viewport, dimension):
        w, h = dimension
        width, height = size
        xLow, yLow, xUp, yUp = viewport
        
        lw = (w*width)/(xUp-xLow)
        lh = (h*height)/(yUp-yLow)
        return (lw, lh)
    
    @staticmethod
    def convertLength(size, viewport, length):
        width, height = size
        xLow, yLow, xUp, yUp = viewport
        
        windowLength = sqrt(width**2 + height**2)
        viewportLength = sqrt((xUp-xLow)**2 + (yUp-yLow)**2)

        llength = (length * windowLength) / viewportLength
        return llength
        
    ### Metodo encargado de actualizar la ubicacion del elemento 
    ### dentro de la ventana en base a su posicion virtual, este metodo
    ### solicita el el tamano de la ventana y el viewport
    def update( self, size, viewport ):
        pass
    
    ### Metodo encargado de mover el elemento dentro del viewport
    def move( self, dx, dy ):
        pass
        
    ### Metodo encargado de pintar el elemento en la ventana, teniendo
    ### en consideracion las coordenadas de la ventana, no del viewport
    def paint( self, painter ):
        pass
    

class Point(Element):
    def __init__( self, location, color, tag = None ):
        Element.__init__(self,tag)
        self.__virtualLocation = location
        self.__color = color
        self.__location = None
    
    def setLocation( self, location ):
        self.__location = location
        
    def getLocation( self ):
        return self.__location
        
    def setVirtualLocation( self, virtualLocation ):
        self.__virtualLocation = virtualLocation
        
    def getVirtualLocation( self ):
        return self.__virtualLocation
        
    def setColor( self, color ):
        self.__color = color
    
    def getColor( self ):
        return self.__color
    
    def update( self, size, viewport ):
        lx, ly = Element.convertCoordinates(size, viewport, self.getVirtualLocation())
        self.setLocation((lx,ly))
    
    def move( self, dx, dy ):
        x, y = self.getVirtualLocation()
        self.setVirtualLocation((x+dx, y+dy))
        
    def paint( self, painter ):
        if self.getLocation() != None:
            x, y = self.getLocation()
            oldPen = painter.pen()
            oldBrush = painter.brush()
            painter.setPen( QtGui.QColor(self.getColor()) )
            painter.setBrush(QtGui.QBrush(QtGui.QColor(self.getColor())))
            painter.drawEllipse(x, y, 2, 2)
            painter.setPen(oldPen)
            painter.setBrush(oldBrush)
            

class Line( Element ):
    
    def __init__( self, point1, point2, color, tag = None ):
        Element.__init__(self,tag)
        self.__virtualPoint1 = point1
        self.__virtualPoint2 = point2
        self.__color = color
        self.__point1 = None
        self.__point2 = None
        
    def setVirtualPoint1( self, virtualPoint1 ):
        self.__virtualPoint1 = virtualPoint1
        
    def getVirtualPoint1( self ):
        return self.__virtualPoint1
        
    def setVirtualPoint2( self, virtualPoint2 ):
        self.__virtualPoint2 = virtualPoint2
        
    def getVirtualPoint2( self ):
        return self.__virtualPoint2
        
    def setColor( self, color ):
        self.__color = color
        
    def getColor( self ):
        return self.__color
        
    def setPoint1( self, point1 ):
        self.__point1 = point1
        
    def getPoint1( self ):
        return self.__point1
        
    def setPoint2( self, point2 ):
        self.__point2 = point2
        
    def getPoint2( self ):
        return self.__point2
        
    def update( self, size, viewport ):
        lx1, ly1 = Element.convertCoordinates(size, viewport, self.getVirtualPoint1())
        lx2, ly2 = Element.convertCoordinates(size, viewport, self.getVirtualPoint2())
        self.setPoint1( (lx1,ly1) )
        self.setPoint2( (lx2,ly2) )
        
    def move( self, dx, dy ):
        x1, y1 = self.getVirtualPoint1()
        x2, y2 = self.getVirtualPoint2()
        
        x1 += dx
        x2 += dx
        y1 += dy
        y2 += dy
        
        self.setVirtualPoint1( [x1,y1] )
        self.setVirtualPoint2( [x2,y2] )
        
    def paint( self, painter ):
        if self.getPoint1() != None and self.getPoint2() != None:
            x1, y1 = self.getPoint1()
            x2, y2 = self.getPoint2()
            oldPen = painter.pen()
            painter.setPen(QtGui.QColor(self.getColor()))
            painter.drawLine(x1, y1, x2, y2)
            painter.setPen( oldPen )
   
class Rectangle( Element ):
    def __init__( self, point1, point2, borderColor, tag = None ):
        Element.__init__(self,tag)
        self.__virtualPoint1 = point1
        self.__virtualPoint2 = point2
        self.__borderColor = borderColor
        self.__point1 = None
        self.__point2 = None
    
    def setVirtualPoint1( self, virtualPoint1 ):
        self.__virtualPoint1 = virtualPoint1
        
    def getVirtualPoint1( self ):
        return self.__virtualPoint1
    
    def setVirtualPoint2( self, virtualPoint2 ):
        self.__virtualPoint2 = virtualPoint2
        
    def getVirtualPoint2( self ):
        return self.__virtualPoint2
            
    def setPoint1( self, point1 ):
        self.__point1 = point1
        
    def getPoint1( self ):
        return self.__point1
    
    def setPoint2( self, point2 ):
        self.__point2 = point2
        
    def getPoint2( self ):
        return self.__point2
        
    def setBorderColor( self, borderColor ):
        self.__borderColor = borderColor
        
    def getBorderColor( self ):
        return self.__borderColor
        
    def update( self, size, viewport ):
        lx1, ly1 = Element.convertCoordinates(size, viewport, self.getVirtualPoint1())
        lx2, ly2 = Element.convertCoordinates(size, viewport, self.getVirtualPoint2())
        
        self.setPoint1((lx1,ly1))
        self.setPoint2((lx2,ly2))
        
    def move( self, dx, dy ):
        x1, y1 = self.getVirtualPoint1()
        x2, y2 = self.getVirtualPoint2()
        
        x1 += dx
        y1 += dy
        x2 += dx
        y2 += dy
        self.setVirtualPoint1((x1,y1))
        self.setVirtualPoint2((x2,y2))
        
    def paint( self, painter ):
        if self.getPoint1() != None and self.getPoint2() != None:
            x1, y1 = self.getPoint1()
            x2, y2 = self.getPoint2()
            width = x2 - x1
            height = y2 - y1
            
            oldPen = painter.pen()
            painter.setPen( QtGui.QColor(self.getBorderColor()) )
            painter.drawRect( x1, y1, width, height )
            painter.setPen( oldPen )
    
class FilledRectangle(Rectangle):
    def __init__( self, point1, point2, borderColor, backgroundColor, tag=None ):
        Rectangle.__init__(self, point1, point2, borderColor, tag)
        self.__backgroundColor = backgroundColor
    
    def setBackgroundColor( self, backgroundColor ):
        self.__backgroundColor = backgroundColor
        
    def getBackgroundColor( self ):
        return self.__backgroundColor
        
    def paint( self, painter ):
        if self.getPoint1() != None and self.getPoint2() != None:
            x1, y1 = self.getPoint1()
            x2, y2 = self.getPoint2()
            width = x2 - x1
            height = y2 - y1
            
            oldPen = painter.pen()
            oldBrush = painter.brush()
            painter.setPen(QtGui.QColor(self.getBorderColor()))
            painter.setBrush(QtGui.QBrush(QtGui.QColor(self.getBackgroundColor())))
            painter.drawRect(x1, y1, width, height)
            painter.setPen(oldPen)
            painter.setBrush(oldBrush)

class Circle(Element):
    def __init__(self, point, size, borderColor, tag=None):
        Element.__init__(self,tag)
        
        self.__virtualPoint = point
        self.__virtualSize = size 
        self.__borderColor = borderColor
        self.__point = None
        self.__size = None
    
    def setVirtualPoint( self, virtualPoint ):
        self.__virtualPoint = virtualPoint
        
    def getVirtualPoint( self ):
        return self.__virtualPoint
        
    def setVirtualSize( self, virtualSize ):
        self.__virtualSize = virtualSize
        
    def getVirtualSize( self ):
        return self.__virtualSize
        
    def setPoint( self, point ):
        self.__point = point
        
    def getPoint( self ):
        return self.__point
        
    def setSize( self, size):
        self.__size = size
        
    def getSize( self ):
        return self.__size
        
    def setBorderColor( self, borderColor ):
        self.__borderColor = borderColor
        
    def getBorderColor( self ):
        return self.__borderColor
        
    def update( self, size, viewport ):
        lx, ly = Element.convertCoordinates(size, viewport, self.getVirtualPoint())
        lw, lh = Element.convertDimension(size, viewport, self.getVirtualSize())
        self.setPoint((lx,ly))
        self.setSize((lw,lh))
        
    def move( self, dx, dy ):
        x, y = self.getVirtualPoint()
        x += dx
        y += dy
        self.setVirtualPoint((x,y))
        
    def paint( self, painter ):
        if self.getPoint() != None and self.getSize() != None:
            x, y = self.getPoint()
            w, h = self.getSize()
            oldPen = painter.pen()
            painter.setPen(QtGui.QColor(self.getBorderColor()))
            painter.drawEllipse(x - w, y - h, w * 2, h * 2)
            painter.setPen( oldPen )
    
class FilledCircle(Circle):
    def __init__(self, point, size, borderColor, backgroundColor, tag=None):
        Circle.__init__(self, point, size, borderColor, tag)
        self.__backgroundColor = backgroundColor
        
    def setBackgroundColor( self, backgroundColor ):
        self.__backgroundColor = backgroundColor
        
    def getBackgroundColor( self ):
        return self.__backgroundColor
        
    def paint( self, painter ):
        if self.getPoint() != None and self.getSize() != None:
            x, y = self.getPoint()
            w, h = self.getSize()
            oldPen = painter.pen()
            oldBrush = painter.brush()
            painter.setPen(QtGui.QColor(self.getBorderColor()))
            painter.setBrush(QtGui.QBrush(QtGui.QColor(self.getBackgroundColor())))
            painter.drawEllipse(x - w, y - h, w * 2, h * 2)
            painter.setBrush(oldBrush)
            painter.setPen(oldPen)
            
class Text( Element ):
    __validAnchors = [ 'CENTER', 'N', 'S', 'E', 'W', 'NE', 'SE', 'NW', 'SW' ]
    
    def __init__( self, location, text, size, anchor, color, tag=None ):
        Element.__init__(self,tag)
        self.__virtualLocation = location
        self.__text = str(text)
        self.__virtualSize = size
        self.__color = color
        self.__location = None
        self.__size = None
        self.__font = None
        self.__dimension = None
        self.setAnchor(anchor)
        
    def __setLocation( self, location ):
        self.__location = location
        
    def __getLocation( self ):
        return self.__location
        
    def __setVirtualLocation( self, virtualLocation ):
        self.__virtualLocation = virtualLocation
        
    def __getVirtualLocation( self ):
        return self.__virtualLocation
        
    def __setVirtualSize( self, virtualSize ):
        self.__virtualSize = virtualSize
        
    def __getVirtualSize( self ):
        return self.__virtualSize
        
    def setColor( self, color ):
        self.__color = color
    
    def getColor( self ):
        return self.__color
        
    def __setSize( self, size ):
        self.__size = size
    
    def getSize( self ):
        return self.__size
        
    def setText( self, text ):
        self.__text = text
    
    def getText( self ):
        return self.__text
        
    def setAnchor( self, anchor ):
        self.__anchor = Text.__validAnchors[0]
        for validAnchor in Text.__validAnchors:
            if validAnchor.upper() == anchor.upper():
                self.__anchor = validAnchor.upper()
                
    def getAnchor( self ):
        return self.__anchor
        
    def update( self, size, viewport ):
        size_ = Element.convertLength(size, viewport, self.__getVirtualSize())
        lx, ly = Element.convertCoordinates(size, viewport, self.__getVirtualLocation())
        self.__setLocation((lx,ly))
        self.__setSize(int(round(size_,0)))
        
    def move( self, dx, dy ):
        x, y = self.__getVirtualLocation()
        self.__setVirtualLocation( [x+dx, y+dy] )
        
    def paint( self, painter ):
        if self.__getLocation() != None and self.getSize() != None:
            font = QtGui.QFont( "Courier", self.getSize() )
            oldFont = painter.font()
            oldPen = painter.pen()
            painter.setFont( font )
            metrics = painter.fontMetrics()
            width = metrics.width( self.getText() )
            height = metrics.ascent()
            x, y = self.__getLocation()
            
            x -= width/2 
            y -= height/2
            if self.getAnchor() == "N" :
                y -= height
            elif self.getAnchor() == "S" :
                y += height
            elif self.getAnchor() == "E" :
                x += width/2 
            elif self.getAnchor() == "W" :
                x -= width/2
            elif self.getAnchor() == "NE" :
                x += width/2 
                y -= height
            elif self.getAnchor() == "NW" :
                x -= width/2
                y -= height
            elif self.getAnchor() == "SE" :
                x += width/2
                y += height
            elif self.getAnchor() == "SW" :
                x -= width/2
                y += height
            
            painter.setPen( QtGui.QColor(self.getColor()) )
            painter.drawText( x, y+height, self.getText() )
            painter.setPen( oldPen )
            painter.setFont( oldFont )
    
class ApplicationLauncher( Thread ):
    def __init__( self ):
        Thread.__init__( self )
        self.__canvas = None
        self.__ready = False
        self.__lock = Lock()
        self.__app = None
        self.__lock.acquire()
        
    def run( self ):
        self.__app = QtGui.QApplication(sys.argv)
        self.__canvas = UtalCanvas()
        self.__canvas.show()
        self.__lock.release()
        sys.exit(self.__app.exec_())

    def getCanvas(self):
        with self.__lock:
            return self.__canvas

class UtalCanvas(QtGui.QWidget):
    
    def __init__(self, size = None, caption = None, background = "white" ):
        super(UtalCanvas, self).__init__()
        self.setWindowFlags( QtCore.Qt.WindowCloseButtonHint | QtCore.Qt.WindowMinimizeButtonHint )
        
        self.__started = False
        self.__elementList = []
        self.__dictId = {}
        self.__dictTag = {}
        self.__nextElementIndex = 0
        self.__lastKeyTime = None
        self.__wasKeyReturned = False
        
        self.setMouseTracking(True)
        self.__mouseButton = None
        self.__mouseXLocation = None
        self.__mouseYLocation = None
        
        self.__keyPressedFlag = False
        self.__KeyRealeasedFlag = False
        self.__keyPressed = None
        self.__wasKeyReturned = False
        self.__keyMode = None       
        
        self.setCaption( caption )
        self.setBackground( background )
        
        # Si size es None la ventana queda de 400x300
        self.setSize( size )
        # La ventana siempre tendra inicialmente un 
        # viewport de (0, 0, 1000, 1000)
        self.__viewport = (0, 0, 1000, 1000)
        self.__setIcon()

    def __setIcon(self):
        matriz = [[4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4294967295L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4294967295L, 4294967295L],
                  [4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4294967295L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4294967295L], 
                  [4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4294967295L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L], 
                  [4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4294967295L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L], 
                  [4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4294967295L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L], 
                  [4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4294967295L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L], 
                  [4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4294967295L, 4294967295L, 4294967295L, 4294967295L, 4294967295L, 4294967295L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L], 
                  [4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4294967295L, 4294967295L, 4294967295L, 4294967295L, 4294967295L, 4294967295L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L], 
                  [4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4294967295L, 4294967295L, 4294967295L, 4294967295L, 4294967295L, 4294967295L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L], 
                  [4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4294967295L, 4294967295L, 4294967295L, 4294967295L, 4294967295L, 4294967295L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L], 
                  [4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4294967295L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L], 
                  [4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4294967295L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L], 
                  [4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4294967295L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L], 
                  [4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4294967295L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L], 
                  [4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4294967295L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4294967295L], 
                  [4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4294967295L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4278190080L, 4294967295L, 4294967295L]]
        image = QtGui.QImage(16, 16, QtGui.QImage.Format_RGB888)
        for i in range(16):
            for j in range(16):
                image.setPixel(i, j, matriz[i][j] )
        pixmap = QtGui.QPixmap.fromImage(image) 
        self.setWindowIcon( QtGui.QIcon(pixmap) )
        
    def setCaption( self, caption ):
        if caption == None:
            self.__caption = "UtalCanvas - v1.0.pg"
        else:
            self.__caption = str(caption)
            
        if self.isStarted():
            self.setWindowTitle( self.__caption )
            
    def getCaption( self ):
        return self.__caption
        
    def setSize( self, size ):
        minimumWidth, minimumHeight = self.__getMinimumSize()        
        try:
            width, height = size
            
            if width < minimumWidth:
                width = minimumWidth
            if height < minimumHeight:
               height = minimumHeight 
            self.__size = (width, height)            
        except:
            self.__size = (minimumWidth, minimumHeight)
        
        width, height = self.__size
        self.setFixedSize(QtCore.QSize(width, height))
        self.__updateElements()
        self.update()
            
    def getSize( self ):
        return self.__size
    
    def setBackground( self, background ):        
        if background == None:
            self.__background = "black"
        else:
            self.__background = background
            
        palette = QtGui.QPalette()
        palette.setBrush(QtGui.QPalette.Window, QtGui.QColor( self.getBackground() ))
        self.setPalette(palette)
            
    def getBackground( self ):
        return self.__background
        
    def __getMinimumSize( self ):
        return (400, 300)
        
    def setStarted( self, started ):
        self.__started = started
        
    def isStarted( self ):
        return self.__started
        
    def getBackground( self ):
        return self.__background
    
    def __updateElements( self ):
        if self.isStarted() :
            for elementId in self.__dictId:
                self.__dictId[elementId].update( self.__size, self.__viewport )
    
    
    def setViewport( self, viewport ):
        if self.isStarted() :
            self.__viewport = viewport
            self.__updateElements()
            self.update()
            
    def getViewport( self ):
        if self.isStarted() :
            return self.__viewport
        return (0, 0, 0, 0)
        
    def move( self, param, dx, dy ):
        try:
            element = self.__dictId[param]        
            element.move( dx, dy )        
            element.update( self.getSize(), self.getViewport() )
            self.update()
            return
        except:
            pass
        
        try:
            tagList = self.__dictTag[param]
            for element in tagList:
                element.move( dx, dy )
                element.update( self.getSize(), self.getViewport() )
                
            self.update()
            return
        except:
            pass
        
    def erase( self, param = None ):

        if param == None:
            self.__elementList = []
            self.__dictId = {}
            self.__dictTag = {}
            self.update()
            return
        
        try:
            element = self.__dictId[param]
            self.__elementList.remove(element)            
            del self.__dictId[element.getId()]            
            if element.getTag() != None:
                self.__dictTag[element.getTag()].remove(element)
            self.update()
            
            return
        except:
            pass
        
        try:
            elementList = self.__dictTag[param]
            for element in elementList:
                self.__elementList.remove(element)
                del self.__dictId[element.getId()]
            del self.__dictTag[param]
            self.update()
            
            return
        except:
            pass
                
    def paintEvent(self, event):
        painter = QtGui.QPainter()
        painter.begin(self)
        #painter.fillRect(event.rect(), QtGui.QBrush(QtCore.Qt.red))
        for element in self.__elementList:
            element.paint(painter)
        painter.end()
        
    def exportImage(self, filename):
        width, height = self.getSize()
        image = QtGui.QImage( width, height, QtGui.QImage.Format_RGB32 )
        painter = QtGui.QPainter()
        painter.begin(image)
        
        oldPen = painter.pen()
        oldBrush = painter.brush()
        painter.setPen(QtGui.QColor(self.getBackground()))
        painter.setBrush(QtGui.QBrush(QtGui.QColor(self.getBackground())))
        painter.drawRect(0, 0, width, height)
        painter.setPen(oldPen)
        painter.setBrush(oldBrush)
        
        for element in self.__elementList :
            element.paint(painter)
        painter.end()
        image.save( filename, "png" )  
        
    def enterEvent( self, event ):
        self.__mouseButton = 0
        
        
    def leaveEvent( self, event ):
        self.__mouseButton = None
        self.__mouseXLocation = None
        self.__mouseYLocation = None
    
    def mouseMoveEvent( self, event ):
        self.__mouseXLocation = event.x()
        self.__mouseYLocation = event.y()
        

    def mousePressEvent( self, event ):
        if event.button() == 1 :
            self.__mouseButton = 1
        elif event.button() == 2:
            self.__mouseButton = 3
        elif event.button() == 4:
            self.__mouseButton = 2
        

    def mouseReleaseEvent( self, event ):
        self.__mouseButton = 0
        
    def convertWindowToViewportCoordintates(self, xWindow, yWindow):
        xLow, yLow, xUp, yUp = self.getViewport()
        width, height = self.getSize()
        
        yWindow = height - yWindow
        
        if xWindow < 0:
            xWindow = 0
        if xWindow > width:
            xWindow = width
        if yWindow < 0:
            yWindow = 0
        if yWindow > height:
            yWindow = width
        
        
        xViewport = (xWindow * (xUp - xLow)) / width
        yViewport = (yWindow * (yUp - yLow)) / height
        
        return xViewport, yViewport
                
                
    def getMouseState( self ):
        if self.__mouseXLocation == None or self.__mouseYLocation == None:
            return (self.__mouseButton, self.__mouseXLocation, self.__mouseYLocation)
        xLocation, yLocation = self.convertWindowToViewportCoordintates(self.__mouseXLocation, self.__mouseYLocation)
        return (self.__mouseButton, xLocation, yLocation)
        
    def keyPressEvent( self, event ):
        
        if event.isAutoRepeat() == False:
            self.__keyPressedFlag = True
            self.__keyReleasedFlag = False
            self.__keyPressed = event.key()
            self.__wasKeyReturned = False
            
        elif self.__keyMode == 2:
            self.__wasKeyReturned = False
        
    def keyReleaseEvent( self, event ):
        
        if event.isAutoRepeat() == False :
            self.__wasKeyReturned = False
            self.__keyReleasedFlag = True
            self.__keyPressedFlag = False
            self.__keyPressed = None
    
    def readKey( self, mode ):
        self.__keyMode = mode
        if mode == 0 :
            if self.__wasKeyReturned == False :
                self.__wasKeyReturned = True
                return self.__keyPressed
            else:
                return None
        elif mode == 1:
            return self.__keyPressed
            
        elif mode == 2:
            
            #while self.__keyPressed == None or self.__wasKeyReturned == True:
            #    pass
            #self.__wasKeyReturned = True
            sleep(0.05)
            return self.__keyPressed
        
    def getIndex( self, keysTuple ):
        try:
            return (list(keysTuple)).index(1)
        except:
            return -1
        
    def getKeyPressed( self, mode ):
        
        repeatDelayTime = 0.5
        currentTime = time()
        if self.__lastKeyTime == None or currentTime - self.__lastKeyTime > repeatDelayTime:
            self.__wasKeyReturned = False
        
        key = None
        
        
        if pygame.key.get_focused():
            if mode == 0 or mode == 1:
                pygame.event.get()
                keys = pygame.key.get_pressed()
                index = self.getIndex( keys )
                name = pygame.key.name(index)
                    
                if name != "unknown key":
                    key = name
            elif mode == 2:
                pygame.event.get()
                keys = pygame.key.get_pressed()
                index = self.getIndex( keys )
                name = pygame.key.name(index)
                while index == -1 or name == "unknown key":
                    pygame.event.get()
                    keys = pygame.key.get_pressed()
                    index = self.getIndex( keys )
                    name = pygame.key.name(index)
                    
                key = name
        
        
        if mode == 0 or mode == 2:
            if self.__wasKeyReturned == False:
                self.__wasKeyReturned = True
                self.__lastKeyTime = time()
                return key
                
            else:
                currentTime = time()
                while currentTime - self.__lastKeyTime <= repeatDelayTime:
                    currentTime = time()
                self.__wasKeyReturned = True
                self.__lastKeyTime = time()
                return key
                
        if mode == 1:
            return key
        

    def __addElement( self, element ):
        element.setId( self.__nextElementIndex )
        element.update( self.__size, self.__viewport )
        self.__nextElementIndex += 1  
        
        self.__elementList += [element]
        self.__dictId[ element.getId() ] = element
        
        if element.getTag() != None :
            try:
                self.__dictTag[ element.getTag() ] += [element]
            except:
                self.__dictTag[ element.getTag() ] = [element]
        
        self.update()
        return element.getId()
        
    def addPoint( self, location, color, tag ):
        if self.isStarted():
            point = Point( location, color, tag )
            return  self.__addElement( point )
            
            
    def addLine( self, point1, point2, color, tag ):
        if self.isStarted():
            line = Line( point1, point2, color, tag )
            return self.__addElement( line )
            
    def addRectangle( self, location, size, color, tag ):
        if self.isStarted():
            rectangle = Rectangle( location, size, color, tag)
            return self.__addElement(rectangle)
    
    def addFilledRectangle( self, location, size, borderColor, filledColor, tag ):
        if self.isStarted():
            rectangle = FilledRectangle( location, size, borderColor, filledColor, tag)
            return self.__addElement(rectangle)
    
    def addCircle( self, location, radius, color, tag ):
        if self.isStarted():
            circle = Circle( location, (radius,radius), color, tag)
            return self.__addElement(circle)
    
    def addFilledCircle( self, location, radius, borderColor, filledColor, tag ):
        if self.isStarted():
            circle = FilledCircle( location, (radius,radius), borderColor, filledColor, tag)
            return self.__addElement(circle)
    
    def addText( self, location, text, size, anchor, color, tag ):
        if self.isStarted():
            text = Text( location, text, size, anchor, color, tag )
            return self.__addElement(text)
    
    

Key_Escape = QtCore.Qt.Key_Escape
Key_Backspace = QtCore.Qt.Key_Backspace
Key_Return = QtCore.Qt.Key_Return
Key_Enter = QtCore.Qt.Key_Enter
Key_Left = QtCore.Qt.Key_Left
Key_Up = QtCore.Qt.Key_Up
Key_Right = QtCore.Qt.Key_Right
Key_Down = QtCore.Qt.Key_Down
Key_Shift = QtCore.Qt.Key_Shift
Key_Control = QtCore.Qt.Key_Control
Key_Meta = QtCore.Qt.Key_Meta
Key_Alt = QtCore.Qt.Key_Alt
Key_AltGr = QtCore.Qt.Key_AltGr
Key_F1 = QtCore.Qt.Key_F1
Key_F2 = QtCore.Qt.Key_F2
Key_F3 = QtCore.Qt.Key_F3
Key_F4 = QtCore.Qt.Key_F4
Key_F5 = QtCore.Qt.Key_F5
Key_F6 = QtCore.Qt.Key_F6
Key_F7 = QtCore.Qt.Key_F7
Key_F8 = QtCore.Qt.Key_F8
Key_F9 = QtCore.Qt.Key_F9
Key_F10 = QtCore.Qt.Key_F10
Key_F11 = QtCore.Qt.Key_F11
Key_F12 = QtCore.Qt.Key_F12
Key_Space = QtCore.Qt.Key_Space
Key_0 = QtCore.Qt.Key_0
Key_1 = QtCore.Qt.Key_1
Key_2 = QtCore.Qt.Key_2
Key_3 = QtCore.Qt.Key_3
Key_4 = QtCore.Qt.Key_4
Key_5 = QtCore.Qt.Key_5
Key_6 = QtCore.Qt.Key_6
Key_7 = QtCore.Qt.Key_7
Key_8 = QtCore.Qt.Key_8
Key_9 = QtCore.Qt.Key_9
Key_A = QtCore.Qt.Key_A
Key_B = QtCore.Qt.Key_B
Key_C = QtCore.Qt.Key_C
Key_D = QtCore.Qt.Key_D
Key_E = QtCore.Qt.Key_E
Key_F = QtCore.Qt.Key_F
Key_G = QtCore.Qt.Key_G
Key_H = QtCore.Qt.Key_H
Key_I = QtCore.Qt.Key_I
Key_J = QtCore.Qt.Key_J
Key_K = QtCore.Qt.Key_K
Key_L = QtCore.Qt.Key_L
Key_M = QtCore.Qt.Key_M
Key_N = QtCore.Qt.Key_N
Key_O = QtCore.Qt.Key_O
Key_P = QtCore.Qt.Key_P
Key_Q = QtCore.Qt.Key_Q
Key_R = QtCore.Qt.Key_R
Key_S = QtCore.Qt.Key_S
Key_T = QtCore.Qt.Key_T
Key_U = QtCore.Qt.Key_U
Key_V = QtCore.Qt.Key_V
Key_W = QtCore.Qt.Key_W
Key_X = QtCore.Qt.Key_X
Key_Y = QtCore.Qt.Key_Y
Key_Z = QtCore.Qt.Key_Z

__colors = {}
__colors["snow"] = QtGui.QColor(255, 250, 250)
__colors["ghost"] = QtGui.QColor(248, 248, 255)
__colors["white"] = QtGui.QColor(245, 245, 245)
__colors["gainsboro"] = QtGui.QColor(220, 220, 220)
__colors["floral"] = QtGui.QColor(255, 250, 240)
__colors["old"] = QtGui.QColor(253, 245, 230)
__colors["linen"] = QtGui.QColor(250, 240, 230)
__colors["antique"] = QtGui.QColor(250, 235, 215)
__colors["papaya"] = QtGui.QColor(255, 239, 213)
__colors["blanched"] = QtGui.QColor(255, 235, 205)
__colors["bisque"] = QtGui.QColor(255, 228, 196)
__colors["peach"] = QtGui.QColor(255, 218, 185)
__colors["navajo"] = QtGui.QColor(255, 222, 173)
__colors["moccasin"] = QtGui.QColor(255, 228, 181)
__colors["cornsilk"] = QtGui.QColor(255, 248, 220)
__colors["ivory"] = QtGui.QColor(255, 255, 240)
__colors["lemon"] = QtGui.QColor(255, 250, 205)
__colors["seashell"] = QtGui.QColor(255, 245, 238)
__colors["honeydew"] = QtGui.QColor(240, 255, 240)
__colors["mint"] = QtGui.QColor(245, 255, 250)
__colors["azure"] = QtGui.QColor(240, 255, 255)
__colors["alice"] = QtGui.QColor(240, 248, 255)
__colors["lavender"] = QtGui.QColor(230, 230, 250)
__colors["lavender"] = QtGui.QColor(255, 240, 245)
__colors["misty"] = QtGui.QColor(255, 228, 225)
__colors["white"] = QtGui.QColor(255, 255, 255)
__colors["black"] = QtGui.QColor(0, 0, 0)
__colors["dark"] = QtGui.QColor(47, 79, 79)
__colors["dim"] = QtGui.QColor(105, 105, 105)
__colors["slate"] = QtGui.QColor(112, 128, 144)
__colors["light"] = QtGui.QColor(119, 136, 153)
__colors["gray"] = QtGui.QColor(190, 190, 190)
__colors["light"] = QtGui.QColor(211, 211, 211)
__colors["midnight"] = QtGui.QColor(25, 25, 112)
__colors["navy"] = QtGui.QColor(0, 0, 128)
__colors["cornflower"] = QtGui.QColor(100, 149, 237)
__colors["dark"] = QtGui.QColor(72, 61, 139)
__colors["slate"] = QtGui.QColor(106, 90, 205)
__colors["medium"] = QtGui.QColor(123, 104, 238)
__colors["light"] = QtGui.QColor(132, 112, 255)
__colors["medium"] = QtGui.QColor(0, 0, 205)
__colors["royal"] = QtGui.QColor(65, 105, 225)
__colors["blue"] = QtGui.QColor(0, 0, 255)
__colors["dodger"] = QtGui.QColor(30, 144, 255)
__colors["deep"] = QtGui.QColor(0, 191, 255)
__colors["sky"] = QtGui.QColor(135, 206, 235)
__colors["light"] = QtGui.QColor(135, 206, 250)
__colors["steel"] = QtGui.QColor(70, 130, 180)
__colors["light"] = QtGui.QColor(176, 196, 222)
__colors["light"] = QtGui.QColor(173, 216, 230)
__colors["powder"] = QtGui.QColor(176, 224, 230)
__colors["pale"] = QtGui.QColor(175, 238, 238)
__colors["dark"] = QtGui.QColor(0, 206, 209)
__colors["medium"] = QtGui.QColor(72, 209, 204)
__colors["turquoise"] = QtGui.QColor(64, 224, 208)
__colors["cyan"] = QtGui.QColor(0, 255, 255)
__colors["light"] = QtGui.QColor(224, 255, 255)
__colors["cadet"] = QtGui.QColor(95, 158, 160)
__colors["medium"] = QtGui.QColor(102, 205, 170)
__colors["aquamarine"] = QtGui.QColor(127, 255, 212)
__colors["dark"] = QtGui.QColor(0, 100, 0)
__colors["dark"] = QtGui.QColor(85, 107, 47)
__colors["dark"] = QtGui.QColor(143, 188, 143)
__colors["sea"] = QtGui.QColor(46, 139, 87)
__colors["medium"] = QtGui.QColor(60, 179, 113)
__colors["light"] = QtGui.QColor(32, 178, 170)
__colors["pale"] = QtGui.QColor(152, 251, 152)
__colors["spring"] = QtGui.QColor(0, 255, 127)
__colors["lawn"] = QtGui.QColor(124, 252, 0)
__colors["green"] = QtGui.QColor(0, 255, 0)
__colors["chartreuse"] = QtGui.QColor(127, 255, 0)
__colors["medium"] = QtGui.QColor(0, 250, 154)
__colors["green"] = QtGui.QColor(173, 255, 47)
__colors["lime"] = QtGui.QColor(50, 205, 50)
__colors["yellow"] = QtGui.QColor(154, 205, 50)
__colors["forest"] = QtGui.QColor(34, 139, 34)
__colors["olive"] = QtGui.QColor(107, 142, 35)
__colors["dark"] = QtGui.QColor(189, 183, 107)
__colors["khaki"] = QtGui.QColor(240, 230, 140)
__colors["pale"] = QtGui.QColor(238, 232, 170)
__colors["light"] = QtGui.QColor(250, 250, 210)
__colors["light"] = QtGui.QColor(255, 255, 224)
__colors["yellow"] = QtGui.QColor(255, 255, 0)
__colors["gold"] = QtGui.QColor(255, 215, 0)
__colors["light"] = QtGui.QColor(238, 221, 130)
__colors["goldenrod"] = QtGui.QColor(218, 165, 32)
__colors["dark"] = QtGui.QColor(184, 134, 11)
__colors["rosy"] = QtGui.QColor(188, 143, 143)
__colors["indian"] = QtGui.QColor(205, 92, 92)
__colors["saddle"] = QtGui.QColor(139, 69, 19)
__colors["sienna"] = QtGui.QColor(160, 82, 45)
__colors["peru"] = QtGui.QColor(205, 133, 63)
__colors["burlywood"] = QtGui.QColor(222, 184, 135)
__colors["beige"] = QtGui.QColor(245, 245, 220)
__colors["wheat"] = QtGui.QColor(245, 222, 179)
__colors["sandy"] = QtGui.QColor(244, 164, 96)
__colors["tan"] = QtGui.QColor(210, 180, 140)
__colors["chocolate"] = QtGui.QColor(210, 105, 30)
__colors["firebrick"] = QtGui.QColor(178, 34, 34)
__colors["brown"] = QtGui.QColor(165, 42, 42)
__colors["dark"] = QtGui.QColor(233, 150, 122)
__colors["salmon"] = QtGui.QColor(250, 128, 114)
__colors["light"] = QtGui.QColor(255, 160, 122)
__colors["orange"] = QtGui.QColor(255, 165, 0)
__colors["dark"] = QtGui.QColor(255, 140, 0)
__colors["coral"] = QtGui.QColor(255, 127, 80)
__colors["light"] = QtGui.QColor(240, 128, 128)
__colors["tomato"] = QtGui.QColor(255, 99, 71)
__colors["orange"] = QtGui.QColor(255, 69, 0)
__colors["red"] = QtGui.QColor(255, 0, 0)
__colors["hot"] = QtGui.QColor(255, 105, 180)
__colors["deep"] = QtGui.QColor(255, 20, 147)
__colors["pink"] = QtGui.QColor(255, 192, 203)
__colors["light"] = QtGui.QColor(255, 182, 193)
__colors["pale"] = QtGui.QColor(219, 112, 147)
__colors["maroon"] = QtGui.QColor(176, 48, 96)
__colors["medium"] = QtGui.QColor(199, 21, 133)
__colors["violet"] = QtGui.QColor(208, 32, 144)
__colors["magenta"] = QtGui.QColor(255, 0, 255)
__colors["violet"] = QtGui.QColor(238, 130, 238)
__colors["plum"] = QtGui.QColor(221, 160, 221)
__colors["orchid"] = QtGui.QColor(218, 112, 214)
__colors["medium"] = QtGui.QColor(186, 85, 211)
__colors["dark"] = QtGui.QColor(153, 50, 204)
__colors["dark"] = QtGui.QColor(148, 0, 211)
__colors["blue"] = QtGui.QColor(138, 43, 226)
__colors["purple"] = QtGui.QColor(160, 32, 240)
__colors["medium"] = QtGui.QColor(147, 112, 219)
__colors["thistle"] = QtGui.QColor(216, 191, 216)
__colors["snow2"] = QtGui.QColor(238, 233, 233)
__colors["snow3"] = QtGui.QColor(205, 201, 201)
__colors["snow4"] = QtGui.QColor(139, 137, 137)
__colors["seashell2"] = QtGui.QColor(238, 229, 222)
__colors["seashell3"] = QtGui.QColor(205, 197, 191)
__colors["seashell4"] = QtGui.QColor(139, 134, 130)
__colors["AntiqueWhite1"] = QtGui.QColor(255, 239, 219)
__colors["AntiqueWhite2"] = QtGui.QColor(238, 223, 204)
__colors["AntiqueWhite3"] = QtGui.QColor(205, 192, 176)
__colors["AntiqueWhite4"] = QtGui.QColor(139, 131, 120)
__colors["bisque2"] = QtGui.QColor(238, 213, 183)
__colors["bisque3"] = QtGui.QColor(205, 183, 158)
__colors["bisque4"] = QtGui.QColor(139, 125, 107)
__colors["PeachPuff2"] = QtGui.QColor(238, 203, 173)
__colors["PeachPuff3"] = QtGui.QColor(205, 175, 149)
__colors["PeachPuff4"] = QtGui.QColor(139, 119, 101)
__colors["NavajoWhite2"] = QtGui.QColor(238, 207, 161)
__colors["NavajoWhite3"] = QtGui.QColor(205, 179, 139)
__colors["NavajoWhite4"] = QtGui.QColor(139, 121, 94)
__colors["LemonChiffon2"] = QtGui.QColor(238, 233, 191)
__colors["LemonChiffon3"] = QtGui.QColor(205, 201, 165)
__colors["LemonChiffon4"] = QtGui.QColor(139, 137, 112)
__colors["cornsilk2"] = QtGui.QColor(238, 232, 205)
__colors["cornsilk3"] = QtGui.QColor(205, 200, 177)
__colors["cornsilk4"] = QtGui.QColor(139, 136, 120)
__colors["ivory2"] = QtGui.QColor(238, 238, 224)
__colors["ivory3"] = QtGui.QColor(205, 205, 193)
__colors["ivory4"] = QtGui.QColor(139, 139, 131)
__colors["honeydew2"] = QtGui.QColor(224, 238, 224)
__colors["honeydew3"] = QtGui.QColor(193, 205, 193)
__colors["honeydew4"] = QtGui.QColor(131, 139, 131)
__colors["LavenderBlush2"] = QtGui.QColor(238, 224, 229)
__colors["LavenderBlush3"] = QtGui.QColor(205, 193, 197)
__colors["LavenderBlush4"] = QtGui.QColor(139, 131, 134)
__colors["MistyRose2"] = QtGui.QColor(238, 213, 210)
__colors["MistyRose3"] = QtGui.QColor(205, 183, 181)
__colors["MistyRose4"] = QtGui.QColor(139, 125, 123)
__colors["azure2"] = QtGui.QColor(224, 238, 238)
__colors["azure3"] = QtGui.QColor(193, 205, 205)
__colors["azure4"] = QtGui.QColor(131, 139, 139)
__colors["SlateBlue1"] = QtGui.QColor(131, 111, 255)
__colors["SlateBlue2"] = QtGui.QColor(122, 103, 238)
__colors["SlateBlue3"] = QtGui.QColor(105, 89, 205)
__colors["SlateBlue4"] = QtGui.QColor(71, 60, 139)
__colors["RoyalBlue1"] = QtGui.QColor(72, 118, 255)
__colors["RoyalBlue2"] = QtGui.QColor(67, 110, 238)
__colors["RoyalBlue3"] = QtGui.QColor(58, 95, 205)
__colors["RoyalBlue4"] = QtGui.QColor(39, 64, 139)
__colors["blue2"] = QtGui.QColor(0, 0, 238)
__colors["blue4"] = QtGui.QColor(0, 0, 139)
__colors["DodgerBlue2"] = QtGui.QColor(28, 134, 238)
__colors["DodgerBlue3"] = QtGui.QColor(24, 116, 205)
__colors["DodgerBlue4"] = QtGui.QColor(16, 78, 139)
__colors["SteelBlue1"] = QtGui.QColor(99, 184, 255)
__colors["SteelBlue2"] = QtGui.QColor(92, 172, 238)
__colors["SteelBlue3"] = QtGui.QColor(79, 148, 205)
__colors["SteelBlue4"] = QtGui.QColor(54, 100, 139)
__colors["DeepSkyBlue2"] = QtGui.QColor(0, 178, 238)
__colors["DeepSkyBlue3"] = QtGui.QColor(0, 154, 205)
__colors["DeepSkyBlue4"] = QtGui.QColor(0, 104, 139)
__colors["SkyBlue1"] = QtGui.QColor(135, 206, 255)
__colors["SkyBlue2"] = QtGui.QColor(126, 192, 238)
__colors["SkyBlue3"] = QtGui.QColor(108, 166, 205)
__colors["SkyBlue4"] = QtGui.QColor(74, 112, 139)
__colors["LightSkyBlue1"] = QtGui.QColor(176, 226, 255)
__colors["LightSkyBlue2"] = QtGui.QColor(164, 211, 238)
__colors["LightSkyBlue3"] = QtGui.QColor(141, 182, 205)
__colors["LightSkyBlue4"] = QtGui.QColor(96, 123, 139)
__colors["SlateGray1"] = QtGui.QColor(198, 226, 255)
__colors["SlateGray2"] = QtGui.QColor(185, 211, 238)
__colors["SlateGray3"] = QtGui.QColor(159, 182, 205)
__colors["SlateGray4"] = QtGui.QColor(108, 123, 139)
__colors["LightSteelBlue1"] = QtGui.QColor(202, 225, 255)
__colors["LightSteelBlue2"] = QtGui.QColor(188, 210, 238)
__colors["LightSteelBlue3"] = QtGui.QColor(162, 181, 205)
__colors["LightSteelBlue4"] = QtGui.QColor(110, 123, 139)
__colors["LightBlue1"] = QtGui.QColor(191, 239, 255)
__colors["LightBlue2"] = QtGui.QColor(178, 223, 238)
__colors["LightBlue3"] = QtGui.QColor(154, 192, 205)
__colors["LightBlue4"] = QtGui.QColor(104, 131, 139)
__colors["LightCyan2"] = QtGui.QColor(209, 238, 238)
__colors["LightCyan3"] = QtGui.QColor(180, 205, 205)
__colors["LightCyan4"] = QtGui.QColor(122, 139, 139)
__colors["PaleTurquoise1"] = QtGui.QColor(187, 255, 255)
__colors["PaleTurquoise2"] = QtGui.QColor(174, 238, 238)
__colors["PaleTurquoise3"] = QtGui.QColor(150, 205, 205)
__colors["PaleTurquoise4"] = QtGui.QColor(102, 139, 139)
__colors["CadetBlue1"] = QtGui.QColor(152, 245, 255)
__colors["CadetBlue2"] = QtGui.QColor(142, 229, 238)
__colors["CadetBlue3"] = QtGui.QColor(122, 197, 205)
__colors["CadetBlue4"] = QtGui.QColor(83, 134, 139)
__colors["turquoise1"] = QtGui.QColor(0, 245, 255)
__colors["turquoise2"] = QtGui.QColor(0, 229, 238)
__colors["turquoise3"] = QtGui.QColor(0, 197, 205)
__colors["turquoise4"] = QtGui.QColor(0, 134, 139)
__colors["cyan2"] = QtGui.QColor(0, 238, 238)
__colors["cyan3"] = QtGui.QColor(0, 205, 205)
__colors["cyan4"] = QtGui.QColor(0, 139, 139)
__colors["DarkSlateGray1"] = QtGui.QColor(151, 255, 255)
__colors["DarkSlateGray2"] = QtGui.QColor(141, 238, 238)
__colors["DarkSlateGray3"] = QtGui.QColor(121, 205, 205)
__colors["DarkSlateGray4"] = QtGui.QColor(82, 139, 139)
__colors["aquamarine2"] = QtGui.QColor(118, 238, 198)
__colors["aquamarine4"] = QtGui.QColor(69, 139, 116)
__colors["DarkSeaGreen1"] = QtGui.QColor(193, 255, 193)
__colors["DarkSeaGreen2"] = QtGui.QColor(180, 238, 180)
__colors["DarkSeaGreen3"] = QtGui.QColor(155, 205, 155)
__colors["DarkSeaGreen4"] = QtGui.QColor(105, 139, 105)
__colors["SeaGreen1"] = QtGui.QColor(84, 255, 159)
__colors["SeaGreen2"] = QtGui.QColor(78, 238, 148)
__colors["SeaGreen3"] = QtGui.QColor(67, 205, 128)
__colors["PaleGreen1"] = QtGui.QColor(154, 255, 154)
__colors["PaleGreen2"] = QtGui.QColor(144, 238, 144)
__colors["PaleGreen3"] = QtGui.QColor(124, 205, 124)
__colors["PaleGreen4"] = QtGui.QColor(84, 139, 84)
__colors["SpringGreen2"] = QtGui.QColor(0, 238, 118)
__colors["SpringGreen3"] = QtGui.QColor(0, 205, 102)
__colors["SpringGreen4"] = QtGui.QColor(0, 139, 69)
__colors["green2"] = QtGui.QColor(0, 238, 0)
__colors["green3"] = QtGui.QColor(0, 205, 0)
__colors["green4"] = QtGui.QColor(0, 139, 0)
__colors["chartreuse2"] = QtGui.QColor(118, 238, 0)
__colors["chartreuse3"] = QtGui.QColor(102, 205, 0)
__colors["chartreuse4"] = QtGui.QColor(69, 139, 0)
__colors["OliveDrab1"] = QtGui.QColor(192, 255, 62)
__colors["OliveDrab2"] = QtGui.QColor(179, 238, 58)
__colors["OliveDrab4"] = QtGui.QColor(105, 139, 34)
__colors["DarkOliveGreen1"] = QtGui.QColor(202, 255, 112)
__colors["DarkOliveGreen2"] = QtGui.QColor(188, 238, 104)
__colors["DarkOliveGreen3"] = QtGui.QColor(162, 205, 90)
__colors["DarkOliveGreen4"] = QtGui.QColor(110, 139, 61)
__colors["khaki1"] = QtGui.QColor(255, 246, 143)
__colors["khaki2"] = QtGui.QColor(238, 230, 133)
__colors["khaki3"] = QtGui.QColor(205, 198, 115)
__colors["khaki4"] = QtGui.QColor(139, 134, 78)
__colors["LightGoldenrod1"] = QtGui.QColor(255, 236, 139)
__colors["LightGoldenrod2"] = QtGui.QColor(238, 220, 130)
__colors["LightGoldenrod3"] = QtGui.QColor(205, 190, 112)
__colors["LightGoldenrod4"] = QtGui.QColor(139, 129, 76)
__colors["LightYellow2"] = QtGui.QColor(238, 238, 209)
__colors["LightYellow3"] = QtGui.QColor(205, 205, 180)
__colors["LightYellow4"] = QtGui.QColor(139, 139, 122)
__colors["yellow2"] = QtGui.QColor(238, 238, 0)
__colors["yellow3"] = QtGui.QColor(205, 205, 0)
__colors["yellow4"] = QtGui.QColor(139, 139, 0)
__colors["gold2"] = QtGui.QColor(238, 201, 0)
__colors["gold3"] = QtGui.QColor(205, 173, 0)
__colors["gold4"] = QtGui.QColor(139, 117, 0)
__colors["goldenrod1"] = QtGui.QColor(255, 193, 37)
__colors["goldenrod2"] = QtGui.QColor(238, 180, 34)
__colors["goldenrod3"] = QtGui.QColor(205, 155, 29)
__colors["goldenrod4"] = QtGui.QColor(139, 105, 20)
__colors["DarkGoldenrod1"] = QtGui.QColor(255, 185, 15)
__colors["DarkGoldenrod2"] = QtGui.QColor(238, 173, 14)
__colors["DarkGoldenrod3"] = QtGui.QColor(205, 149, 12)
__colors["DarkGoldenrod4"] = QtGui.QColor(139, 101, 8)
__colors["RosyBrown1"] = QtGui.QColor(255, 193, 193)
__colors["RosyBrown2"] = QtGui.QColor(238, 180, 180)
__colors["RosyBrown3"] = QtGui.QColor(205, 155, 155)
__colors["RosyBrown4"] = QtGui.QColor(139, 105, 105)
__colors["IndianRed1"] = QtGui.QColor(255, 106, 106)
__colors["IndianRed2"] = QtGui.QColor(238, 99, 99)
__colors["IndianRed3"] = QtGui.QColor(205, 85, 85)
__colors["IndianRed4"] = QtGui.QColor(139, 58, 58)
__colors["sienna1"] = QtGui.QColor(255, 130, 71)
__colors["sienna2"] = QtGui.QColor(238, 121, 66)
__colors["sienna3"] = QtGui.QColor(205, 104, 57)
__colors["sienna4"] = QtGui.QColor(139, 71, 38)
__colors["burlywood1"] = QtGui.QColor(255, 211, 155)
__colors["burlywood2"] = QtGui.QColor(238, 197, 145)
__colors["burlywood3"] = QtGui.QColor(205, 170, 125)
__colors["burlywood4"] = QtGui.QColor(139, 115, 85)
__colors["wheat1"] = QtGui.QColor(255, 231, 186)
__colors["wheat2"] = QtGui.QColor(238, 216, 174)
__colors["wheat3"] = QtGui.QColor(205, 186, 150)
__colors["wheat4"] = QtGui.QColor(139, 126, 102)
__colors["tan1"] = QtGui.QColor(255, 165, 79)
__colors["tan2"] = QtGui.QColor(238, 154, 73)
__colors["tan4"] = QtGui.QColor(139, 90, 43)
__colors["chocolate1"] = QtGui.QColor(255, 127, 36)
__colors["chocolate2"] = QtGui.QColor(238, 118, 33)
__colors["chocolate3"] = QtGui.QColor(205, 102, 29)
__colors["firebrick1"] = QtGui.QColor(255, 48, 48)
__colors["firebrick2"] = QtGui.QColor(238, 44, 44)
__colors["firebrick3"] = QtGui.QColor(205, 38, 38)
__colors["firebrick4"] = QtGui.QColor(139, 26, 26)
__colors["brown1"] = QtGui.QColor(255, 64, 64)
__colors["brown2"] = QtGui.QColor(238, 59, 59)
__colors["brown3"] = QtGui.QColor(205, 51, 51)
__colors["brown4"] = QtGui.QColor(139, 35, 35)
__colors["salmon1"] = QtGui.QColor(255, 140, 105)
__colors["salmon2"] = QtGui.QColor(238, 130, 98)
__colors["salmon3"] = QtGui.QColor(205, 112, 84)
__colors["salmon4"] = QtGui.QColor(139, 76, 57)
__colors["LightSalmon2"] = QtGui.QColor(238, 149, 114)
__colors["LightSalmon3"] = QtGui.QColor(205, 129, 98)
__colors["LightSalmon4"] = QtGui.QColor(139, 87, 66)
__colors["orange2"] = QtGui.QColor(238, 154, 0)
__colors["orange3"] = QtGui.QColor(205, 133, 0)
__colors["orange4"] = QtGui.QColor(139, 90, 0)
__colors["DarkOrange1"] = QtGui.QColor(255, 127, 0)
__colors["DarkOrange2"] = QtGui.QColor(238, 118, 0)
__colors["DarkOrange3"] = QtGui.QColor(205, 102, 0)
__colors["DarkOrange4"] = QtGui.QColor(139, 69, 0)
__colors["coral1"] = QtGui.QColor(255, 114, 86)
__colors["coral2"] = QtGui.QColor(238, 106, 80)
__colors["coral3"] = QtGui.QColor(205, 91, 69)
__colors["coral4"] = QtGui.QColor(139, 62, 47)
__colors["tomato2"] = QtGui.QColor(238, 92, 66)
__colors["tomato3"] = QtGui.QColor(205, 79, 57)
__colors["tomato4"] = QtGui.QColor(139, 54, 38)
__colors["OrangeRed2"] = QtGui.QColor(238, 64, 0)
__colors["OrangeRed3"] = QtGui.QColor(205, 55, 0)
__colors["OrangeRed4"] = QtGui.QColor(139, 37, 0)
__colors["red2"] = QtGui.QColor(238, 0, 0)
__colors["red3"] = QtGui.QColor(205, 0, 0)
__colors["red4"] = QtGui.QColor(139, 0, 0)
__colors["DebianRed"] = QtGui.QColor(215, 7, 81)
__colors["DeepPink2"] = QtGui.QColor(238, 18, 137)
__colors["DeepPink3"] = QtGui.QColor(205, 16, 118)
__colors["DeepPink4"] = QtGui.QColor(139, 10, 80)
__colors["HotPink1"] = QtGui.QColor(255, 110, 180)
__colors["HotPink2"] = QtGui.QColor(238, 106, 167)
__colors["HotPink3"] = QtGui.QColor(205, 96, 144)
__colors["HotPink4"] = QtGui.QColor(139, 58, 98)
__colors["pink1"] = QtGui.QColor(255, 181, 197)
__colors["pink2"] = QtGui.QColor(238, 169, 184)
__colors["pink3"] = QtGui.QColor(205, 145, 158)
__colors["pink4"] = QtGui.QColor(139, 99, 108)
__colors["LightPink1"] = QtGui.QColor(255, 174, 185)
__colors["LightPink2"] = QtGui.QColor(238, 162, 173)
__colors["LightPink3"] = QtGui.QColor(205, 140, 149)
__colors["LightPink4"] = QtGui.QColor(139, 95, 101)
__colors["PaleVioletRed1"] = QtGui.QColor(255, 130, 171)
__colors["PaleVioletRed2"] = QtGui.QColor(238, 121, 159)
__colors["PaleVioletRed3"] = QtGui.QColor(205, 104, 137)
__colors["PaleVioletRed4"] = QtGui.QColor(139, 71, 93)
__colors["maroon1"] = QtGui.QColor(255, 52, 179)
__colors["maroon2"] = QtGui.QColor(238, 48, 167)
__colors["maroon3"] = QtGui.QColor(205, 41, 144)
__colors["maroon4"] = QtGui.QColor(139, 28, 98)
__colors["VioletRed1"] = QtGui.QColor(255, 62, 150)
__colors["VioletRed2"] = QtGui.QColor(238, 58, 140)
__colors["VioletRed3"] = QtGui.QColor(205, 50, 120)
__colors["VioletRed4"] = QtGui.QColor(139, 34, 82)
__colors["magenta2"] = QtGui.QColor(238, 0, 238)
__colors["magenta3"] = QtGui.QColor(205, 0, 205)
__colors["magenta4"] = QtGui.QColor(139, 0, 139)
__colors["orchid1"] = QtGui.QColor(255, 131, 250)
__colors["orchid2"] = QtGui.QColor(238, 122, 233)
__colors["orchid3"] = QtGui.QColor(205, 105, 201)
__colors["orchid4"] = QtGui.QColor(139, 71, 137)
__colors["plum1"] = QtGui.QColor(255, 187, 255)
__colors["plum2"] = QtGui.QColor(238, 174, 238)
__colors["plum3"] = QtGui.QColor(205, 150, 205)
__colors["plum4"] = QtGui.QColor(139, 102, 139)
__colors["MediumOrchid1"] = QtGui.QColor(224, 102, 255)
__colors["MediumOrchid2"] = QtGui.QColor(209, 95, 238)
__colors["MediumOrchid3"] = QtGui.QColor(180, 82, 205)
__colors["MediumOrchid4"] = QtGui.QColor(122, 55, 139)
__colors["DarkOrchid1"] = QtGui.QColor(191, 62, 255)
__colors["DarkOrchid2"] = QtGui.QColor(178, 58, 238)
__colors["DarkOrchid3"] = QtGui.QColor(154, 50, 205)
__colors["DarkOrchid4"] = QtGui.QColor(104, 34, 139)
__colors["purple1"] = QtGui.QColor(155, 48, 255)
__colors["purple2"] = QtGui.QColor(145, 44, 238)
__colors["purple3"] = QtGui.QColor(125, 38, 205)
__colors["purple4"] = QtGui.QColor(85, 26, 139)
__colors["MediumPurple1"] = QtGui.QColor(171, 130, 255)
__colors["MediumPurple2"] = QtGui.QColor(159, 121, 238)
__colors["MediumPurple3"] = QtGui.QColor(137, 104, 205)
__colors["MediumPurple4"] = QtGui.QColor(93, 71, 139)
__colors["thistle1"] = QtGui.QColor(255, 225, 255)
__colors["thistle2"] = QtGui.QColor(238, 210, 238)
__colors["thistle3"] = QtGui.QColor(205, 181, 205)
__colors["thistle4"] = QtGui.QColor(139, 123, 139)
__colors["gray1"] = QtGui.QColor(3, 3, 3)
__colors["gray2"] = QtGui.QColor(5, 5, 5)
__colors["gray3"] = QtGui.QColor(8, 8, 8)
__colors["gray4"] = QtGui.QColor(10, 10, 10)
__colors["gray5"] = QtGui.QColor(13, 13, 13)
__colors["gray6"] = QtGui.QColor(15, 15, 15)
__colors["gray7"] = QtGui.QColor(18, 18, 18)
__colors["gray8"] = QtGui.QColor(20, 20, 20)
__colors["gray9"] = QtGui.QColor(23, 23, 23)
__colors["gray10"] = QtGui.QColor(26, 26, 26)
__colors["gray11"] = QtGui.QColor(28, 28, 28)
__colors["gray12"] = QtGui.QColor(31, 31, 31)
__colors["gray13"] = QtGui.QColor(33, 33, 33)
__colors["gray14"] = QtGui.QColor(36, 36, 36)
__colors["gray15"] = QtGui.QColor(38, 38, 38)
__colors["gray16"] = QtGui.QColor(41, 41, 41)
__colors["gray17"] = QtGui.QColor(43, 43, 43)
__colors["gray18"] = QtGui.QColor(46, 46, 46)
__colors["gray19"] = QtGui.QColor(48, 48, 48)
__colors["gray20"] = QtGui.QColor(51, 51, 51)
__colors["gray21"] = QtGui.QColor(54, 54, 54)
__colors["gray22"] = QtGui.QColor(56, 56, 56)
__colors["gray23"] = QtGui.QColor(59, 59, 59)
__colors["gray24"] = QtGui.QColor(61, 61, 61)
__colors["gray25"] = QtGui.QColor(64, 64, 64)
__colors["gray26"] = QtGui.QColor(66, 66, 66)
__colors["gray27"] = QtGui.QColor(69, 69, 69)
__colors["gray28"] = QtGui.QColor(71, 71, 71)
__colors["gray29"] = QtGui.QColor(74, 74, 74)
__colors["gray30"] = QtGui.QColor(77, 77, 77)
__colors["gray31"] = QtGui.QColor(79, 79, 79)
__colors["gray32"] = QtGui.QColor(82, 82, 82)
__colors["gray33"] = QtGui.QColor(84, 84, 84)
__colors["gray34"] = QtGui.QColor(87, 87, 87)
__colors["gray35"] = QtGui.QColor(89, 89, 89)
__colors["gray36"] = QtGui.QColor(92, 92, 92)
__colors["gray37"] = QtGui.QColor(94, 94, 94)
__colors["gray38"] = QtGui.QColor(97, 97, 97)
__colors["gray39"] = QtGui.QColor(99, 99, 99)
__colors["gray40"] = QtGui.QColor(102, 102, 102)
__colors["gray42"] = QtGui.QColor(107, 107, 107)
__colors["gray43"] = QtGui.QColor(110, 110, 110)
__colors["gray44"] = QtGui.QColor(112, 112, 112)
__colors["gray45"] = QtGui.QColor(115, 115, 115)
__colors["gray46"] = QtGui.QColor(117, 117, 117)
__colors["gray47"] = QtGui.QColor(120, 120, 120)
__colors["gray48"] = QtGui.QColor(122, 122, 122)
__colors["gray49"] = QtGui.QColor(125, 125, 125)
__colors["gray50"] = QtGui.QColor(127, 127, 127)
__colors["gray51"] = QtGui.QColor(130, 130, 130)
__colors["gray52"] = QtGui.QColor(133, 133, 133)
__colors["gray53"] = QtGui.QColor(135, 135, 135)
__colors["gray54"] = QtGui.QColor(138, 138, 138)
__colors["gray55"] = QtGui.QColor(140, 140, 140)
__colors["gray56"] = QtGui.QColor(143, 143, 143)
__colors["gray57"] = QtGui.QColor(145, 145, 145)
__colors["gray58"] = QtGui.QColor(148, 148, 148)
__colors["gray59"] = QtGui.QColor(150, 150, 150)
__colors["gray60"] = QtGui.QColor(153, 153, 153)
__colors["gray61"] = QtGui.QColor(156, 156, 156)
__colors["gray62"] = QtGui.QColor(158, 158, 158)
__colors["gray63"] = QtGui.QColor(161, 161, 161)
__colors["gray64"] = QtGui.QColor(163, 163, 163)
__colors["gray65"] = QtGui.QColor(166, 166, 166)
__colors["gray66"] = QtGui.QColor(168, 168, 168)
__colors["gray67"] = QtGui.QColor(171, 171, 171)
__colors["gray68"] = QtGui.QColor(173, 173, 173)
__colors["gray69"] = QtGui.QColor(176, 176, 176)
__colors["gray70"] = QtGui.QColor(179, 179, 179)
__colors["gray71"] = QtGui.QColor(181, 181, 181)
__colors["gray72"] = QtGui.QColor(184, 184, 184)
__colors["gray73"] = QtGui.QColor(186, 186, 186)
__colors["gray74"] = QtGui.QColor(189, 189, 189)
__colors["gray75"] = QtGui.QColor(191, 191, 191)
__colors["gray76"] = QtGui.QColor(194, 194, 194)
__colors["gray77"] = QtGui.QColor(196, 196, 196)
__colors["gray78"] = QtGui.QColor(199, 199, 199)
__colors["gray79"] = QtGui.QColor(201, 201, 201)
__colors["gray80"] = QtGui.QColor(204, 204, 204)
__colors["gray81"] = QtGui.QColor(207, 207, 207)
__colors["gray82"] = QtGui.QColor(209, 209, 209)
__colors["gray83"] = QtGui.QColor(212, 212, 212)
__colors["gray84"] = QtGui.QColor(214, 214, 214)
__colors["gray85"] = QtGui.QColor(217, 217, 217)
__colors["gray86"] = QtGui.QColor(219, 219, 219)
__colors["gray87"] = QtGui.QColor(222, 222, 222)
__colors["gray88"] = QtGui.QColor(224, 224, 224)
__colors["gray89"] = QtGui.QColor(227, 227, 227)
__colors["gray90"] = QtGui.QColor(229, 229, 229)
__colors["gray91"] = QtGui.QColor(232, 232, 232)
__colors["gray92"] = QtGui.QColor(235, 235, 235)
__colors["gray93"] = QtGui.QColor(237, 237, 237)
__colors["gray94"] = QtGui.QColor(240, 240, 240)
__colors["gray95"] = QtGui.QColor(242, 242, 242)
__colors["gray97"] = QtGui.QColor(247, 247, 247)
__colors["gray98"] = QtGui.QColor(250, 250, 250)
__colors["gray99"] = QtGui.QColor(252, 252, 252)
__colors["dark"] = QtGui.QColor(169, 169, 169)


__app = None
__canvas = None

def __applicationIsReady():
    global __canvas
    global __app
    
    return __app != None and __canvas != None and __app.isAlive()

def show_window():
    global __canvas
    global __app
        
    if __app == None or __app.isAlive():
        __app = ApplicationLauncher()
        __app.start()
        __canvas = __app.getCanvas()
        __canvas.setStarted(True)
        
def __getValidColor( supposedColor ):
    try:
        color = __colors[supposedColor]
        return color
    except:
        if isinstance( supposedColor, QtGui.QColor ) :
            return supposedColor   
    return __colors["black"]

def create_color( red, green, blue ):
    red = int(red)
    green = int(green)
    blue = int(blue)
    
    if red < 0: red = 0
    if green < 0: green = 0
    if blue < 0: blue = 0
    if red > 255: red = 255
    if green > 255: green = 255
    if blue > 255: blue = 255
    
    return QtGui.QColor(red, green, blue)

###  Dibuja el punto y devuelve un indice para poder borrarlo. Si no se indica 
### color, se toma 'black' por defecto.
def create_point( x, y, color = "black", tag = None ):
    global __canvas
    if __applicationIsReady() :
        color = __getValidColor( color )
        return __canvas.addPoint( (x, y), color, tag )


### Dibuja la linea y devuelve un ndice para poder borrarla. Si no se indica 
### color, se toma 'black' por defecto.
def create_line(x1, y1, x2, y2, color = "black", tag = None ):
    global __canvas
    if __applicationIsReady() :
        color = __getValidColor( color )
        return __canvas.addLine( (x1, y1), (x2, y2), color, tag )
    

### Dibuja el circulo y devuelve un indice para poder borrarlo. Si no se indica 
### color, se toma 'black' por defecto.
def create_circle( x, y, radius, borderColor = "black", tag = None ) :
    global __canvas
    if __applicationIsReady() :
        borderColor = __getValidColor( borderColor )
        return __canvas.addCircle( (x, y), radius, borderColor, tag )


### Idem al anterior pero relleno. Si solo se indica un color, se tomara como color exterior y de relleno
def create_filled_circle(x, y, radius, borderColor = "black" , backgroundColor = None, tag = None ):
    global __canvas
    if backgroundColor == None :
        backgroundColor = borderColor
    
    if __applicationIsReady() :
        borderColor = __getValidColor( borderColor )
        backgroundColor = __getValidColor( backgroundColor )
        return __canvas.addFilledCircle( (x, y), radius, borderColor, backgroundColor, tag )


###
### Metodo auxiliar para ordenar las coordenadas de pasadas como parametro para
### los metodos de dibujo de los rectangulos y para window_coordinates
###
def __fixCoordinates( x1, y1, x2, y2 ):
    xMin = x1
    xMax = x2
    if x2 < x1 :
        xMin = x2
        xMax = x1
        
    yMin = y1
    yMax = y2
    if y2 < y1 :
        yMin = y2
        yMax = y1
    
    return ( xMin, yMin, xMax, yMax )


### Dibuja el rectangulo y devuelve un indice para poder borrarlo. Si no se 
### indica color, se toma 'black' por defecto.
###
### Este metodo corrige las coordenadas si fueron pasadas en orden inverso
### con el metodo __fixCoordinates
###
def create_rectangle( x1, y1, x2, y2, borderColor = "black", tag = None ):
    global __canvas
    if __applicationIsReady() :
        xMin, yMin, xMax, yMax = __fixCoordinates( x1, y1, x2, y2 )
        borderColor = __getValidColor( borderColor )
        return __canvas.addRectangle( (xMin, yMin), (xMax, yMax), borderColor, tag )
    

### Idem al anterior pero relleno. Si solo se indica un color, se tomara como 
### color exterior y de relleno.
###
### Este metodo corrige las coordenadas si fueron pasadas en orden inverso
### con el metodo __fixCoordinates
###
def create_filled_rectangle(x1, y1, x2, y2, borderColor = "black", backgroundColor = None, tag = None ):
    global __canvas
    if backgroundColor == None :
        backgroundColor = borderColor
        
    if __applicationIsReady() :
        xMin, yMin, xMax, yMax = __fixCoordinates( x1, y1, x2, y2 )
        borderColor = __getValidColor( borderColor )
        backgroundColor = __getValidColor( backgroundColor )
        return __canvas.addFilledRectangle( (xMin, yMin), (xMax, yMax) , borderColor, backgroundColor, tag )


### Escribe el texto cadena en la ventana grafica. El parametro ancla 
### puede tomar los siguientes valores: 'CENTER', 'N', 'S', 'E', 'W', 'NE', 
### 'SE', 'NW' y 'SW'. Si no se pone size, toma el valor 10, del mismo modo 
### ancla toma el valor 'CENTER' y colortexto 'black'.
def create_text(x, y, text, size = 10 , anchor = "CENTER", color = "black", tag = None ):
    global __canvas
    if __applicationIsReady() :
        color = __getValidColor( color )
        return __canvas.addText( (x, y), text, size, anchor, color, tag )
    
    
### Borra un objeto dado su indice.
### Borra todos los objetos con dicha etiqueta.
### Borra todos los objetos de la ventana grafica (si no se pasa parametro)
def erase( param = None ):
    global __canvas
    if __applicationIsReady() :
        __canvas.erase( param )
        

### Desplaza una distancia relativa el objeto con dicho indice.
### Desplaza una distancia relativa (a cada objeto) todos los objetos con dicha etiqueta.
def move( param, xInc, yInc):
    global __canvas
    if __applicationIsReady() :
        __canvas.move( param, xInc, yInc)
        
        
### Tamano fisico en pixels de la ventana grafica. Si se llama a esta funcion sin argumentos, 
### devuelve una lista con los valores actuales.
def window_size( width = None, height = None ):
    if __applicationIsReady() :
        if width == None and height == None:
            return __canvas.getSize()
        else:
            __canvas.setSize( (width, height) )    


### Tamano logico de la ventana grafica. Si se llama a esta funcion sin argumentos, 
### devuelve una lista con los valores actuales.
###
### Al realizar el cambio del tamano logico, se actualizan todos los objetos agregados
### tamano y ubicacion. La unica excepcion es el tamano del texto, que se mantiene
### invariante
###
### Este metodo corrige las coordenadas si fueron pasadas en orden inverso
### con el metodo __fixCoordinates
###
def window_coordinates( xLow = None, yLow = None, xUp = None, yUp = None ):
    if __applicationIsReady() :
        if xLow == None or yLow == None or xUp == None or yUp == None :
            return __canvas.getViewport()
        else:
            xMin, yMin, xMax, yMax = __fixCoordinates( xLow, yLow, xUp, yUp )
            __canvas.setViewport( (xMin, yMin, xMax, yMax) )


### En PythonG la ventana grafica puede tardar algun tiempo en actualizarse despues 
### de utilizar una funcion de dibujo. Llamando a esta funcion se actualiza explicitamente 
### la ventana grafica.
###
### PROBLEMA SOLUCUIONADO EN UtalCanvas. El metodo igualmente repinta la ventana.
###

def window_update():
    global __canvas
    if __applicationIsReady() :
        __canvas.update()
        

### Devuelve la tupla (boton,posx,posy) donde boton puede ser 0 (si no hay ningun boton pulsado) 
### o un entero del 1 al 3 que identifica que boton se encuentra actualmente pulsado 
### (1:izq. 2:central 3:der.). Los otros dos elementos de la tupla (posx y posy) 
### son las coordenadas del raton en la ventana grafica. Si el raton se encuentra 
### fuera de la ventana grafica esta funcion devuelve (None,None,None). 
### IMPORTANTE: debes tener cuidado al utilizar esta funcion, pues cada vez que se pulsa 
### un boton, este se encuentra pulsado durante varios milisegundos, sufiente para 
### que sucesivas llamadas a esta funcion devuelvan los mismos valores. Por esto, 
### necesitas asegurarte de que el boton se ha soltado antes de volver a mirar si 
### se ha pulsado de nuevo.
def mouse_state():
    global __canvas
    if __applicationIsReady() :
        return __canvas.getMouseState()
    else:
        return None, None, None
    
### Lee una tecla sin hacer echo por pantalla. Funciona de tres modos diferentes 
### segun el valor del parametro:
###     * keypressed(0): No espera tecla + retardo de repeticion. Si cuando se llama a 
###         esta funcion hay una tecla pulsada, la devuelve. Si no hay ninguna pulsada, 
###         devuelve None. El retardo de repeticion evita que una pulsacion genere mas de un caracter.
###     * keypressed(1): No espera tecla + sin retardo de repeticion. Identico al anterior, 
###         excepto que no hay retardo de repeticion por lo que cada pulsacion de una tecla 
###         suele generar varios caracteres. Este modo suele utilizarse en ciertos tipos de 
###         juegos (ojo no sirve para nada mas).
###     * keypressed(2): Espera tecla + retardo de repeticion. Espera hasta que se pulse 
###         una tecla. Incorpora retardo de repeticion para evitar que una pulsacion genere 
###         mas de un caracter. Es el modo por defecto si no se indica ningun parametro.

def keypressed( mode = 2 ):
    global __canvas
    if __applicationIsReady() :
        return __canvas.readKey( mode )
    

### Permite definir un titulo, un color de fondo de la ventana grafica.
### Por defecto, colorfondo toma el valor 'white'.

def window_style(titulo, colorfondo="white"):
    global __app
    global __canvas
    if __applicationIsReady():
        colorfondo = __getValidColor( colorfondo )
        __canvas.setBackground( colorfondo )
        __canvas.setWindowTitle(titulo)
        
### Se cierra todo y termina el programa. 

def close_window():
    global __canvas
    if __applicationIsReady() :
        __canvas.close()
    
def save_image( filename ):
    global __canvas
    if __applicationIsReady() :
        __canvas.exportImage( filename )